#!/usr/bin/env python3
"""
Fire Alarm System - 开发状态标识
==================================
版本: 1.0.0
开发阶段: 已完成 (2025年7月)
当前状态: 进入定期维护与功能扩展阶段
维护说明: 核心功能开发已完成，后续将进行bug修复和功能优化
"""
import os
import sys
import time
import threading
import RPi.GPIO as GPIO
import configparser
import psutil
import board
import adafruit_ssd1306
from adafruit_dht import DHT11, DHT22, AM2302
from sensor_control import sensor_status, dht_data

__version__ = "2.0"

def save_config(config):
    """保存配置到文件"""
    with open('config.ini', 'w') as f:
        config.write(f)

# 导入自定义模块
from config import load_config
from sensor_control import init_gpio, init_i2c, check_sensors, reset_sensors, manual_reset_sensors, detect_rtc_battery_status, detect_oled_status, detect_led_status
from logger import setup_logger

# 初始化日志
logger = setup_logger()
logger.info(f"火灾报警系统 v{__version__} 启动")

# 全局变量
alarm_active = False
minor_smoke_detected = False
button_press_time = None
simple_mode = False
config = None
mqtt_client = None
mqtt_connected = False
gui_root = None
# I2C设备检测结果
detected_i2c_devices = []
# 添加试运行模式标志和GPIO针脚映射
simulation_mode = False

# 初始化Tkinter变量
import tkinter as tk

gui_status_vars = {
    'flame': tk.StringVar(value='正常'),
    'smoke': tk.StringVar(value='正常'),
    'temperature': tk.StringVar(value='-- °C'),
    'humidity': tk.StringVar(value='-- %'),
    'green_led': tk.StringVar(value='正常'),
    'red_led': tk.StringVar(value='正常'),
    'oled': tk.StringVar(value='正常'),
    'rtc_battery': tk.StringVar(value='正常'),
    'ip': tk.StringVar(value='获取中...'),
    'time': tk.StringVar(value='同步中...'),
    'mqtt_status': tk.StringVar(value='未连接')
}
sensor_reset_manual = False
last_reset_time = time.time()

# OLED显示函数
def clear_display():
    """清空OLED显示"""
    if 'oled' in globals():
        oled.fill(0)

def display_text(line, text):
    """在指定行显示文本"""
    if 'oled' in globals():
        oled.text(text, 0, line * 10, 1)

def update_oled():
    """更新OLED显示"""
    if 'oled' in globals():
        oled.show()

def get_ip():
    """获取IP地址"""
    import socket
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM):
            s.connect(('8.8.8.8', 80))
            ip = s.getsockname()[0]
        return ip
    except Exception as e:
        logger.error(f"获取IP失败: {e}")
        return '未知'

def create_tray_icon():
    """创建系统托盘图标"""
    try:
        from pystray import Icon as TrayIcon, Menu as TrayMenu, MenuItem as TrayMenuItem
        from PIL import Image, ImageDraw

        def create_image():
            width = 64
            height = 64
            color1 = "green"
            color2 = "white"

            image = Image.new('RGB', (width, height), color1)
            dc = ImageDraw.Draw(image)
            dc.rectangle(
                (width // 4, height // 4, width * 3 // 4, height * 3 // 4),
                fill=color2)
            return image

        def on_quit(icon, item):
            icon.stop()
            if gui_root:
                gui_root.quit()
            GPIO.cleanup()
            sys.exit(0)

        menu = TrayMenu(TrayMenuItem('退出', on_quit))
        icon = TrayIcon("FireAlarm", create_image(), "火灾报警系统", menu)

        threading.Thread(target=icon.run, daemon=True).start()
    except Exception as e:
        logger.warning(f"系统托盘图标创建失败: {e}")

def button_pressed(channel):
    """按钮按下回调函数"""
    global button_press_time
    if button_press_time is None:
        button_press_time = time.time()
    else:
        if time.time() - button_press_time < 2:
            manual_reset_sensors()
        button_press_time = None

def create_gui(root):
    """创建图形用户界面"""
    import tkinter as tk
    from tkinter import ttk, messagebox
    global gui_root
    gui_root = root
    gui_root.title("火灾报警系统")
    gui_root.geometry("800x480")

    # 设置字体
    default_font = ('SimHei', 10)
    gui_root.option_add('*Font', default_font)

    # 创建主框架
    main_frame = ttk.Frame(gui_root, padding=10)
    main_frame.pack(fill=tk.BOTH, expand=True)

    # 试运行模式选项
    mode_frame = ttk.Frame(main_frame)
    mode_frame.pack(fill=tk.X, pady=5)
    ttk.Label(mode_frame, text="试运行模式: ").pack(side=tk.LEFT)
    sim_checkbox = ttk.Checkbutton(mode_frame, text="不连接传感器运行", variable=tk.BooleanVar(value=simulation_mode), command=lambda: setattr(sys.modules[__name__], 'simulation_mode', sim_checkbox.var.get()))
    sim_checkbox.var = sim_checkbox['variable']
    sim_checkbox.pack(side=tk.LEFT)

    # GPIO针脚信息区域
    gpio_frame = ttk.LabelFrame(main_frame, text="GPIO针脚映射", padding=10)
    gpio_frame.pack(fill=tk.X, pady=5)
    gpio_text = tk.Text(gpio_frame, height=8, width=40, state='disabled')
    gpio_text.pack(fill=tk.X)
    gpio_text.config(state='normal')
    gpio_text.insert(tk.END, "传感器及设备GPIO针脚配置:\n")
    for device, pin in gpio_pin_mapping.items():
        gpio_text.insert(tk.END, f"{device}: GPIO{pin}\n")
    gpio_text.config(state='disabled')

    # 标题
    title_label = ttk.Label(main_frame, text="火灾报警系统状态监控", font=('SimHei', 16, 'bold'))
    title_label.pack(pady=10)

    # 状态框架
    status_frame = ttk.LabelFrame(main_frame, text="系统状态", padding=10)
    status_frame.pack(fill=tk.X, pady=5)

    # 传感器复位按钮
    reset_frame = ttk.Frame(main_frame)
    reset_frame.pack(fill=tk.X, pady=5)
    ttk.Button(reset_frame, text="传感器复位", command=manual_reset_sensors).pack(side=tk.RIGHT)

    # 状态标签
    status_grid = ttk.Frame(status_frame)
    status_grid.pack(fill=tk.X)

    status_items = [
    ('火焰传感器:', 'flame'),
    ('烟雾传感器:', 'smoke'),
    ('温度:', 'temperature'),
    ('湿度:', 'humidity'),
    ('绿灯状态:', 'green_led'),
    ('红灯状态:', 'red_led'),
    ('OLED状态:', 'oled'),
    ('IP地址:', 'ip'),
    ('系统时间:', 'time'),
    ('MQTT状态:', 'mqtt_status')
]

    # 动态添加RTC电池状态（如果检测到）
    if 'rtc_battery' in sensor_status and sensor_status['rtc_battery'] != 'not_detected':
        status_items.insert(7, ('RTC电池状态:', 'rtc_battery'))

    for i, (label_text, var_name) in enumerate(status_items):
        ttk.Label(status_grid, text=label_text, width=15).grid(row=i//3, column=(i%3)*2, sticky=tk.W, pady=5, padx=5)
        ttk.Label(status_grid, textvariable=gui_status_vars[var_name], width=20, 
                 foreground='red' if var_name in ['flame', 'smoke'] else 'black').grid(row=i//3, column=(i%3)*2+1, sticky=tk.W, pady=5)

    return gui_root

def generate_simulated_data():
    """生成模拟传感器数据"""
    import random
    # 模拟温湿度
    dht_data['temperature'] = round(random.uniform(20.0, 30.0), 1)
    dht_data['humidity'] = round(random.uniform(30.0, 70.0), 1)
    # 模拟传感器状态
    sensor_status['flame'] = 'normal'
    sensor_status['smoke'] = 'normal'
    sensor_status['green_led'] = 'normal'
    sensor_status['red_led'] = 'normal'
    sensor_status['oled'] = 'normal'
    # 随机生成故障状态（10%概率）
    if random.random() < 0.1:
        sensor_status[random.choice(['flame', 'smoke', 'green_led', 'red_led', 'oled'])] = 'failure'


def main():
    global config, simple_mode, last_reset_time, sensor_reset_manual

    # 解析命令行参数
    simple_mode = '--simple' in sys.argv or '-s' in sys.argv
    simulation_mode = '--simulate' in sys.argv or '-m' in sys.argv

    # 命令行模式输出系统信息
if simple_mode or '-m' in sys.argv:
            print("火灾报警系统 - {0}运行模式".format("模拟" if simulation_mode else "正常"))
            print("传感器及设备GPIO针脚配置:")
            for device, pin in gpio_pin_mapping.items():
                print(f"{device}: GPIO{pin}")
            
            # I2C设备信息
            print("\nI2C设备检测:")
            if detected_i2c_devices:
                print(f"已发现: {', '.join(detected_i2c_devices)}")
                known_devices = {
                    '0x3C': 'OLED显示屏',
                    '0x48': 'ADC转换器',
                    '0x50': 'EEPROM存储器',
                    '0x68': 'RTC实时时钟'
                }
                identified = [known_devices.get(addr, f'未知设备 {addr}') for addr in detected_i2c_devices]
                print(f"识别: {', '.join(identified)}")
            else:
                print("未发现I2C设备")
            
            # MQTT配置检查
            mqtt_configured = config.has_section('MQTT') and all(config.has_option('MQTT', opt) for opt in ['broker', 'port', 'topic'])
            if not mqtt_configured:
                print("\n警告: MQTT未正确配置，将以离线模式运行")
            
            if simulation_mode:
                print("\n模拟数据:")

    # 加载配置
config = load_config()

    # 从配置文件加载GPIO引脚映射
global gpio_pin_mapping
gpio_pin_mapping = {
        '火焰传感器': config.getint('GPIO', 'flame_sensor', fallback=17),
        '烟雾传感器': config.getint('GPIO', 'smoke_sensor', fallback=27),
        '绿灯': config.getint('GPIO', 'green_led', fallback=5),
        '红灯': config.getint('GPIO', 'red_led', fallback=6),
        '按钮': config.getint('GPIO', 'button', fallback=23),
        'OLED SDA': config.getint('GPIO', 'oled_sda', fallback=2),
        'OLED SCL': config.getint('GPIO', 'oled_scl', fallback=3),
        '温湿度传感器': config.getint('GPIO', 'dht_sensor', fallback=4),
        '蜂鸣器': config.getint('GPIO', 'buzzer', fallback=18)
    }

    # 配置验证
required_sections = ['SENSORS', 'GPIO', 'ALERTS']
for section in required_sections:
    if not config.has_section(section):
        logger.error(f"配置文件缺少必要部分: {section}")
        raise ValueError(f"配置文件缺少必要部分: {section}")

# 验证传感器阈值
try:
    sensor_reset_interval = config.getint('SENSORS', 'reset_interval')
    check_interval = config.getfloat('SENSORS', 'check_interval')
    temp_threshold = config.getfloat('ALERTS', 'temperature_threshold')
    smoke_threshold = config.getint('ALERTS', 'smoke_threshold')
    
    if sensor_reset_interval <= 0 or check_interval <= 0:
        raise ValueError("时间间隔必须为正数")
    if temp_threshold <= 0 or smoke_threshold <= 0:
        raise ValueError("阈值必须为正数")

except (ValueError, configparser.Error) as e:
    logger.error(f"配置验证失败: {str(e)}")
    raise

    # 初始化GPIO和I2C（模拟模式下跳过）
if not simulation_mode:
    try:
        init_gpio()
        # 从配置获取传感器型号
        dht_model = config.get('SENSORS', 'dht_model', fallback='DHT11')
        oled_model = config.get('OLED', 'model', fallback='SSD1306')
        
        # 初始化I2C并扫描设备
        i2c = board.I2C()
        
        # 扫描I2C设备地址
        i2c_addresses = i2c.scan()
        detected_i2c_devices = [f"0x{addr:02X}" for addr in i2c_addresses]
        
        # 在简单模式下打印I2C设备信息
        if simple_mode:
            print(f"检测到I2C设备: {', '.join(detected_i2c_devices) if detected_i2c_devices else '无'}")
        
        # 初始化OLED
        if oled_model == 'SSD1306':
            oled = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c)
        elif oled_model == 'SH1106':
            oled = adafruit_ssd1306.SH1106_I2C(128, 64, i2c)
        else:
            logger.error(f"不支持的OLED型号: {oled_model}")
            raise ValueError(f"不支持的OLED型号: {oled_model}")
        
        # 初始化温湿度传感器
        dht_pin = gpio_pin_mapping['温湿度传感器']
        if dht_model == 'DHT11':
            dht_sensor = DHT11(getattr(board, f'D{dht_pin}'))
        elif dht_model == 'DHT22':
            dht_sensor = DHT22(getattr(board, f'D{dht_pin}'))
        elif dht_model == 'AM2302':
            dht_sensor = AM2302(getattr(board, f'D{dht_pin}'))
        else:
            logger.error(f"不支持的温湿度传感器型号: {dht_model}")
            raise ValueError(f"不支持的温湿度传感器型号: {dht_model}")
        
        # 初始化火焰传感器
        flame_model = config.get('SENSORS', 'flame_model', fallback='KY-026')
        flame_pin = gpio_pin_mapping['火焰传感器']
        if flame_model in ['KY-026', 'FLAME-01', 'GP2Y0A21YK']:
            # 通用模拟火焰传感器初始化
            GPIO.setup(flame_pin, GPIO.IN)
            logger.info(f"已初始化火焰传感器 {flame_model}，引脚: GPIO{flame_pin}")
        else:
            logger.error(f"不支持的火焰传感器型号: {flame_model}")
            raise ValueError(f"不支持的火焰传感器型号: {flame_model}")
        
        logger.info("硬件初始化成功")
    except Exception as e:
        logger.critical(f"硬件初始化失败: {str(e)}", exc_info=True)
        if not simulation_mode:
            GPIO.cleanup()
        sys.exit(1)

    # 设置按钮中断
try:
    GPIO.add_event_detect(23, GPIO.FALLING, callback=button_pressed, bouncetime=200)
except Exception as e:
    logger.error(f"按钮中断设置失败: {str(e)}")

    # 创建系统托盘图标
    create_tray_icon()

    # 如果不是简单模式，创建GUI
    if not simple_mode:
        import tkinter as tk
        from tkinter import ttk
        # 创建主Tk实例
        gui_root = tk.Tk()
        gui_root.withdraw()  # 隐藏主窗口
        
        # 创建启动弹窗
        splash_root = tk.Toplevel(gui_root)
        splash_root.title("设备检测")
        splash_root.geometry("300x200")
        splash_root.overrideredirect(True)  # 无边框窗口
        splash_root.attributes('-topmost', True)  # 置顶
        
        # 居中显示
        screen_width = splash_root.winfo_screenwidth()
        screen_height = splash_root.winfo_screenheight()
        x = (screen_width - 300) // 2
        y = (screen_height - 200) // 2
        splash_root.geometry(f"300x200+{x}+{y}")
        
        # 添加标题和内容
        ttk.Label(splash_root, text="火灾报警系统", font=('SimHei', 14, 'bold')).pack(pady=10)
        
        # I2C设备检测详情
        i2c_frame = ttk.Frame(splash_root)
        i2c_frame.pack(fill=tk.X, padx=20, pady=5)
        ttk.Label(i2c_frame, text="I2C设备检测:").pack(anchor=tk.W)
        
        if detected_i2c_devices:
            device_list = ttk.Label(i2c_frame, text=f"已发现: {', '.join(detected_i2c_devices)}")
            device_list.pack(anchor=tk.W)
            
            # 识别常见I2C设备
            known_devices = {
                '0x3C': 'OLED显示屏',
                '0x48': 'ADC转换器',
                '0x50': 'EEPROM存储器',
                '0x68': 'RTC实时时钟'
            }
            identified = [known_devices.get(addr, f'未知设备 {addr}') for addr in detected_i2c_devices]
            ttk.Label(i2c_frame, text=f"识别: {', '.join(identified)}").pack(anchor=tk.W)
        else:
            ttk.Label(i2c_frame, text="未发现I2C设备", foreground='orange').pack(anchor=tk.W)
        
        # 系统状态
        status_var = tk.StringVar(value="系统启动中...")
        ttk.Label(splash_root, textvariable=status_var).pack(pady=5)
        
        # 检查MQTT配置
        mqtt_configured = config.has_section('MQTT') and all(config.has_option('MQTT', opt) for opt in ['broker', 'port', 'topic'])
        if not mqtt_configured:
            status_var.set("MQTT未配置，将以离线模式运行")
            ttk.Label(splash_root, text="警告: MQTT未正确配置", foreground='red').pack(pady=5)
        
        # 2秒后关闭弹窗并显示主窗口
        def close_splash():
            splash_root.destroy()
            gui_root.deiconify()  # 显示主窗口
            create_gui(gui_root)  # 构建主GUI
        
        splash_root.after(2000, close_splash)
        gui_root.mainloop()

    def update_gui_status():
        """更新GUI状态显示"""
        if not gui_root:  # 非GUI模式不更新
            return
        
        try:
            # 更新传感器状态
            status_map = {
                'normal': '正常',
                'failure': '故障',
                'charging': '充电中'
            }
            
            for key in ['flame', 'smoke', 'green_led', 'red_led', 'oled', 'rtc_battery']:
                if key in sensor_status:
                    gui_status_vars[key].set(status_map.get(sensor_status[key], '未知'))
                    # 设置故障状态为红色
                    if sensor_status[key] == 'failure':
                        for widget in gui_root.winfo_children():
                            if isinstance(widget, ttk.Frame):
                                for child in widget.winfo_children():
                                    if isinstance(child, ttk.Frame):
                                        for label in child.winfo_children():
                                            if hasattr(label, 'cget') and label.cget('textvariable') == gui_status_vars[key]:
                                                label.config(foreground='red')
            
            # 更新温湿度数据
            gui_status_vars['temperature'].set(f"{dht_data.get('temperature', '--')} °C")
            gui_status_vars['humidity'].set(f"{dht_data.get('humidity', '--')} %")
            
            # 更新系统时间
            gui_status_vars['time'].set(time.strftime('%Y-%m-%d %H:%M:%S'))
        except Exception as e:
            logger.error(f"GUI状态更新失败: {str(e)}")
    
    try:
        # 更新传感器状态
        status_map = {
            'normal': '正常',
            'failure': '故障',
            'charging': '充电中'
        }
        
        for key in ['flame', 'smoke', 'green_led', 'red_led', 'oled', 'rtc_battery']:
            if key in sensor_status:
                gui_status_vars[key].set(status_map.get(sensor_status[key], '未知'))
                # 设置故障状态为红色
                if sensor_status[key] == 'failure':
                    for widget in gui_root.winfo_children():
                        if isinstance(widget, ttk.Frame):
                            for child in widget.winfo_children():
                                if isinstance(child, ttk.Frame):
                                    for label in child.winfo_children():
                                        if hasattr(label, 'cget') and label.cget('textvariable') == gui_status_vars[key]:
                                            label.config(foreground='red')
        
        # 更新温湿度数据
        gui_status_vars['temperature'].set(f"{dht_data.get('temperature', '--')} °C")
        gui_status_vars['humidity'].set(f"{dht_data.get('humidity', '--')} %")
        
        # 更新系统时间
        gui_status_vars['time'].set(time.strftime('%Y-%m-%d %H:%M:%S'))
    except Exception as e:
        logger.error(f"GUI状态更新失败: {str(e)}")
            
        # 更新传感器状态
        status_map = {
            'normal': '正常',
            'failure': '故障',
            'charging': '充电中'
        }
        
        for key in ['flame', 'smoke', 'green_led', 'red_led', 'oled', 'rtc_battery']:
            if key in sensor_status:
                gui_status_vars[key].set(status_map.get(sensor_status[key], '未知'))
                # 设置故障状态为红色
                if sensor_status[key] == 'failure':
                    for widget in gui_root.winfo_children():
                        if isinstance(widget, ttk.Frame):
                            for child in widget.winfo_children():
                                if isinstance(child, ttk.Frame):
                                    for label in child.winfo_children():
                                        if hasattr(label, 'cget') and label.cget('textvariable') == gui_status_vars[key]:
                                            label.config(foreground='red')
        
        # 更新温湿度数据
        gui_status_vars['temperature'].set(f"{dht_data.get('temperature', '--')} °C")
        gui_status_vars['humidity'].set(f"{dht_data.get('humidity', '--')} %")
        
        # 更新系统时间
        gui_status_vars['time'].set(time.strftime('%Y-%m-%d %H:%M:%S'))

# 资源清理函数
    def cleanup_resources():
        """释放所有硬件资源"""
        try:
            logger.info("开始资源清理...")
            # 停止报警
            if 'GPIO' in sys.modules:
                try:
                    GPIO.output(5, GPIO.LOW)  # 关闭绿灯
                    GPIO.output(6, GPIO.LOW)  # 关闭红灯
                    GPIO.cleanup()
                    logger.info("GPIO资源已释放")
                except Exception as e:
                    logger.error(f"GPIO清理失败: {str(e)}")
            
            # 关闭I2C设备
            if 'oled' in globals():
                try:
                    oled.fill(0)
                    oled.show()
                    logger.info("OLED显示已关闭")
                except Exception as e:
                    logger.error(f"OLED清理失败: {str(e)}")
            
            # 关闭MQTT连接
            if mqtt_connected and mqtt_client:
                try:
                    mqtt_client.disconnect()
                    logger.info("MQTT连接已关闭")
                except Exception as e:
                    logger.error(f"MQTT断开失败: {str(e)}")
        except Exception as e:
            logger.error(f"资源清理错误: {str(e)}")

    # 设置程序退出信号处理
    def signal_handler(sig, frame):
        logger.info(f"接收到退出信号: {sig}")
        cleanup_resources()
        sys.exit(0)

    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    # 主循环
    try:
        check_interval = config.getfloat('SENSORS', 'check_interval', fallback=0.5)
        # 启动硬件状态检测线程
        def hardware_check_thread():
            logger.info("硬件检测线程已启动")
            while True:
                try:
                    detect_oled_status()
                    detect_led_status()
                    detect_rtc_battery_status()
                    
                    # 检测蜂鸣器状态
                    buzzer_pin = gpio_pin_mapping.get('蜂鸣器')
                    if buzzer_pin:
                        try:
                            GPIO.setup(buzzer_pin, GPIO.OUT)
                            GPIO.output(buzzer_pin, GPIO.LOW)
                            sensor_status['buzzer'] = 'normal'
                        except Exception as e:
                            sensor_status['buzzer'] = 'failure'
                            logger.error(f"蜂鸣器检测失败: {e}")
                    else:
                        sensor_status['buzzer'] = 'not_connected'
                        logger.warning("蜂鸣器引脚未配置")
                    
                    # 检查LED和蜂鸣器状态
                    missing_devices = []
                    if sensor_status.get('green_led') == 'failure':
                        missing_devices.append('绿灯')
                    if sensor_status.get('red_led') == 'failure':
                        missing_devices.append('红灯')
                    if sensor_status.get('buzzer') == 'failure':
                        missing_devices.append('蜂鸣器')
                    
                    if missing_devices:
                        message = f"没有找到所需的{', '.join(missing_devices)}，建议添加以了解系统状态。"
                        logger.warning(message)
                        
                        # GUI模式下显示提示
                        if not simple_mode and gui_root:
                            def show_warning():
                                from tkinter import messagebox
                                messagebox.showwarning("设备缺失", message)
                            gui_root.after(0, show_warning)
                        # CLI模式下输出提示
                        elif simple_mode:
                            print(f"警告: {message}")
                    
                    time.sleep(check_interval)  # 按照配置的检测间隔休眠
                except Exception as e:
                    logger.error(f"硬件检测线程出错: {e}", exc_info=True)
                    time.sleep(1)  # 出错后短暂休眠再重试
        
        logger.info("准备启动硬件检测线程...")
        threading.Thread(target=hardware_check_thread, daemon=True).start()
        
        while True:
            current_time = time.time()

            # 传感器自动复位检查
            if current_time - last_reset_time >= sensor_reset_interval * 24 * 3600:
                logger.info(f"达到自动复位间隔({sensor_reset_interval}天)，执行传感器复位")
                reset_sensors()
                last_reset_time = current_time

            # 传感器手动复位检查
            if sensor_reset_manual:
                reset_sensors()
                sensor_reset_manual = False
                # 更新配置文件
                config.set('SENSORS', 'reset_manual', 'false')
                save_config(config)

            # 检查传感器状态
            if simulation_mode:
                generate_simulated_data()
                alarm_triggered = False
                alarm_type = None
            else:
                alarm_triggered, alarm_type = check_sensors()
            if alarm_triggered:
                # 处理报警逻辑
                pass

            # 更新GUI状态
            update_gui_status()

            # 命令行模式下输出模拟数据
            if simulation_mode and (simple_mode or '-m' in sys.argv):
                print(f"[{time.strftime('%H:%M:%S')}] 温度: {dht_data.get('temperature', '--')} °C, 湿度: {dht_data.get('humidity', '--')} %")
                print(f"[{time.strftime('%H:%M:%S')}] 火焰传感器: {sensor_status.get('flame', '未知')}, 烟雾传感器: {sensor_status.get('smoke', '未知')}")
                print("-" * 50)

            # 非模拟模式下检查传感器故障
            if not simulation_mode:
                failed_sensors = [k for k, v in sensor_status.items() if v == 'failure']
                if failed_sensors:
                    # GUI模式下显示弹窗
                    if not simple_mode and gui_root:
                        messagebox.showerror("传感器故障", f"以下传感器可能损坏: {', '.join(failed_sensors)}")
                    # CLI模式下输出到控制台
                    else:
                        logger.error(f"传感器故障: 以下传感器可能损坏 - {', '.join(failed_sensors)}")
                    # 重置故障状态以避免重复提醒
                    for sensor in failed_sensors:
                        sensor_status[sensor] = 'normal'

            time.sleep(check_interval)

    except KeyboardInterrupt:
        logger.info("程序被用户中断")
    except Exception as e:
        logger.error(f"主循环错误: {e}")
    finally:
        GPIO.cleanup()

if __name__ == '__main__':
    main()